{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "np.random.seed(12345)\n",
    "np.set_printoptions(precision=4, suppress=True)\n",
    "pd.options.display.max_rows = 25\n",
    "pd.options.display.max_columns = 20\n",
    "pd.options.display.max_colwidth = 82\n",
    "plt.rc(\"figure\", figsize=(10, 6))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:06.414910Z",
     "end_time": "2024-04-24T20:22:08.772158Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 10.1 GroupBy机制"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "data": {
      "text/plain": "  key1 key2     data1     data2\n0    a  one -0.204708  1.393406\n1    a  two  0.478943  0.092908\n2    b  one -0.519439  0.281746\n3    b  two -0.555730  0.769023\n4    a  one  1.965781  1.246435",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>key1</th>\n      <th>key2</th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>a</td>\n      <td>one</td>\n      <td>-0.204708</td>\n      <td>1.393406</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>a</td>\n      <td>two</td>\n      <td>0.478943</td>\n      <td>0.092908</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>b</td>\n      <td>one</td>\n      <td>-0.519439</td>\n      <td>0.281746</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>b</td>\n      <td>two</td>\n      <td>-0.555730</td>\n      <td>0.769023</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>a</td>\n      <td>one</td>\n      <td>1.965781</td>\n      <td>1.246435</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],\n",
    "                   'key2': ['one', 'two', 'one', 'two', 'one'],\n",
    "                   'data1': np.random.standard_normal(5),\n",
    "                   'data2': np.random.standard_normal(5)})\n",
    "df"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.772158Z",
     "end_time": "2024-04-24T20:22:08.832723Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "data": {
      "text/plain": "<pandas.core.groupby.generic.SeriesGroupBy object at 0x000002389C18E590>"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped = df['data1'].groupby(df['key1'])\n",
    "grouped"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.800398Z",
     "end_time": "2024-04-24T20:22:08.876848Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "key1\na    0.746672\nb   -0.537585\nName: data1, dtype: float64"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped.mean()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.817091Z",
     "end_time": "2024-04-24T20:22:08.882892Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "data": {
      "text/plain": "key1  key2\na     one     0.880536\n      two     0.478943\nb     one    -0.519439\n      two    -0.555730\nName: data1, dtype: float64"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "means = df['data1'].groupby([df['key1'], df['key2']]).mean()\n",
    "means"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.832723Z",
     "end_time": "2024-04-24T20:22:08.958962Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "data": {
      "text/plain": "key2       one       two\nkey1                    \na     0.880536  0.478943\nb    -0.519439 -0.555730",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th>key2</th>\n      <th>one</th>\n      <th>two</th>\n    </tr>\n    <tr>\n      <th>key1</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>a</th>\n      <td>0.880536</td>\n      <td>0.478943</td>\n    </tr>\n    <tr>\n      <th>b</th>\n      <td>-0.519439</td>\n      <td>-0.555730</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "means.unstack()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.856539Z",
     "end_time": "2024-04-24T20:22:08.973156Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "data": {
      "text/plain": "California  2005    0.478943\n            2006   -0.519439\nOhio        2005   -0.380219\n            2006    1.965781\nName: data1, dtype: float64"
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])\n",
    "years = np.array([2005, 2005, 2006, 2005, 2006])\n",
    "df['data1'].groupby([states, years]).mean()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.877841Z",
     "end_time": "2024-04-24T20:22:08.973156Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "data": {
      "text/plain": "         data1     data2\nkey1                    \na     0.746672  0.910916\nb    -0.537585  0.525384",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n    <tr>\n      <th>key1</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>a</th>\n      <td>0.746672</td>\n      <td>0.910916</td>\n    </tr>\n    <tr>\n      <th>b</th>\n      <td>-0.537585</td>\n      <td>0.525384</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby('key1').mean(numeric_only=True)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.904292Z",
     "end_time": "2024-04-24T20:22:08.973156Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "data": {
      "text/plain": "              data1     data2\nkey1 key2                    \na    one   0.880536  1.319920\n     two   0.478943  0.092908\nb    one  -0.519439  0.281746\n     two  -0.555730  0.769023",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n    <tr>\n      <th>key1</th>\n      <th>key2</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">a</th>\n      <th>one</th>\n      <td>0.880536</td>\n      <td>1.319920</td>\n    </tr>\n    <tr>\n      <th>two</th>\n      <td>0.478943</td>\n      <td>0.092908</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">b</th>\n      <th>one</th>\n      <td>-0.519439</td>\n      <td>0.281746</td>\n    </tr>\n    <tr>\n      <th>two</th>\n      <td>-0.555730</td>\n      <td>0.769023</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby(['key1', 'key2']).mean()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.926246Z",
     "end_time": "2024-04-24T20:22:08.973156Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "key1  key2\na     one     2\n      two     1\nb     one     1\n      two     1\ndtype: int64"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby(['key1', 'key2']).size()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.939728Z",
     "end_time": "2024-04-24T20:22:08.973156Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 对分组进行迭代"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n",
      "  key1 key2     data1     data2\n",
      "0    a  one -0.204708  1.393406\n",
      "1    a  two  0.478943  0.092908\n",
      "4    a  one  1.965781  1.246435\n",
      "b\n",
      "  key1 key2     data1     data2\n",
      "2    b  one -0.519439  0.281746\n",
      "3    b  two -0.555730  0.769023\n"
     ]
    }
   ],
   "source": [
    "for name, group in df.groupby('key1'):\n",
    "    print(name)\n",
    "    print(group)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.964501Z",
     "end_time": "2024-04-24T20:22:09.068478Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('a', 'one')\n",
      "  key1 key2     data1     data2\n",
      "0    a  one -0.204708  1.393406\n",
      "4    a  one  1.965781  1.246435\n",
      "('a', 'two')\n",
      "  key1 key2     data1     data2\n",
      "1    a  two  0.478943  0.092908\n",
      "('b', 'one')\n",
      "  key1 key2     data1     data2\n",
      "2    b  one -0.519439  0.281746\n",
      "('b', 'two')\n",
      "  key1 key2    data1     data2\n",
      "3    b  two -0.55573  0.769023\n"
     ]
    }
   ],
   "source": [
    "for (k1, k2), group in df.groupby(['key1', 'key2']):\n",
    "    print((k1, k2))\n",
    "    print(group)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:08.994737Z",
     "end_time": "2024-04-24T20:22:09.116804Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "data": {
      "text/plain": "  key1 key2     data1     data2\n2    b  one -0.519439  0.281746\n3    b  two -0.555730  0.769023",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>key1</th>\n      <th>key2</th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>2</th>\n      <td>b</td>\n      <td>one</td>\n      <td>-0.519439</td>\n      <td>0.281746</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>b</td>\n      <td>two</td>\n      <td>-0.555730</td>\n      <td>0.769023</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pieces = dict(list(df.groupby('key1')))\n",
    "pieces['b']"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.006006Z",
     "end_time": "2024-04-24T20:22:09.215434Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "data": {
      "text/plain": "key1      object\nkey2      object\ndata1    float64\ndata2    float64\ndtype: object"
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dtypes"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.026719Z",
     "end_time": "2024-04-24T20:22:09.225097Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "float64\n",
      "      data1     data2\n",
      "0 -0.204708  1.393406\n",
      "1  0.478943  0.092908\n",
      "2 -0.519439  0.281746\n",
      "3 -0.555730  0.769023\n",
      "4  1.965781  1.246435\n",
      "object\n",
      "  key1 key2\n",
      "0    a  one\n",
      "1    a  two\n",
      "2    b  one\n",
      "3    b  two\n",
      "4    a  one\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\1123782164.py:1: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.\n",
      "  grouped = df.groupby(df.dtypes, axis=1)\n"
     ]
    }
   ],
   "source": [
    "grouped = df.groupby(df.dtypes, axis=1)\n",
    "for dtype, group in grouped:\n",
    "    print(dtype)\n",
    "    print(group)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.044813Z",
     "end_time": "2024-04-24T20:22:09.245764Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 选取一列或列的子集"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "data": {
      "text/plain": "<pandas.core.groupby.generic.SeriesGroupBy object at 0x00000238ACF9FF40>"
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby('key1')['data1']"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.071756Z",
     "end_time": "2024-04-24T20:22:09.349343Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "data": {
      "text/plain": "<pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000238ACF9F9A0>"
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby('key1')[['data2']]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.111251Z",
     "end_time": "2024-04-24T20:22:09.406990Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "data": {
      "text/plain": "<pandas.core.groupby.generic.SeriesGroupBy object at 0x00000238ACFF8100>"
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['data1'].groupby(df['key1'])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.138036Z",
     "end_time": "2024-04-24T20:22:09.406990Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "data": {
      "text/plain": "<pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000238ACFF8190>"
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[['data2']].groupby(df['key1'])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.172954Z",
     "end_time": "2024-04-24T20:22:09.444876Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "data": {
      "text/plain": "              data2\nkey1 key2          \na    one   1.319920\n     two   0.092908\nb    one   0.281746\n     two   0.769023",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>data2</th>\n    </tr>\n    <tr>\n      <th>key1</th>\n      <th>key2</th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">a</th>\n      <th>one</th>\n      <td>1.319920</td>\n    </tr>\n    <tr>\n      <th>two</th>\n      <td>0.092908</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">b</th>\n      <th>one</th>\n      <td>0.281746</td>\n    </tr>\n    <tr>\n      <th>two</th>\n      <td>0.769023</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby(['key1', 'key2'])[['data2']].mean()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.193445Z",
     "end_time": "2024-04-24T20:22:09.444876Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 通过字典或Series进行分组"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "data": {
      "text/plain": "               a         b         c         d         e\nJoe     1.007189 -1.296221  0.274992  0.228913  1.352917\nSteve   0.886429 -2.001637 -0.371843  1.669025 -0.438570\nWes    -0.539741       NaN       NaN -1.021228 -0.577087\nJim     0.124121  0.302614  0.523772  0.000940  1.343810\nTravis -0.713544 -0.831154 -2.370232 -1.860761 -0.860757",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>a</th>\n      <th>b</th>\n      <th>c</th>\n      <th>d</th>\n      <th>e</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>Joe</th>\n      <td>1.007189</td>\n      <td>-1.296221</td>\n      <td>0.274992</td>\n      <td>0.228913</td>\n      <td>1.352917</td>\n    </tr>\n    <tr>\n      <th>Steve</th>\n      <td>0.886429</td>\n      <td>-2.001637</td>\n      <td>-0.371843</td>\n      <td>1.669025</td>\n      <td>-0.438570</td>\n    </tr>\n    <tr>\n      <th>Wes</th>\n      <td>-0.539741</td>\n      <td>NaN</td>\n      <td>NaN</td>\n      <td>-1.021228</td>\n      <td>-0.577087</td>\n    </tr>\n    <tr>\n      <th>Jim</th>\n      <td>0.124121</td>\n      <td>0.302614</td>\n      <td>0.523772</td>\n      <td>0.000940</td>\n      <td>1.343810</td>\n    </tr>\n    <tr>\n      <th>Travis</th>\n      <td>-0.713544</td>\n      <td>-0.831154</td>\n      <td>-2.370232</td>\n      <td>-1.860761</td>\n      <td>-0.860757</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "people = pd.DataFrame(np.random.randn(5, 5),\n",
    "                      columns=['a', 'b', 'c', 'd', 'e'],\n",
    "                      index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])\n",
    "people.iloc[2:3, [1, 2]] = np.nan\n",
    "people"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.208340Z",
     "end_time": "2024-04-24T20:22:09.504104Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\658935620.py:2: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.\n",
      "  by_column = people.groupby(mapping, axis=1)\n"
     ]
    },
    {
     "data": {
      "text/plain": "            blue       red\nJoe     0.503905  1.063885\nSteve   1.297183 -1.553778\nWes    -1.021228 -1.116829\nJim     0.524712  1.770545\nTravis -4.230992 -2.405455",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>blue</th>\n      <th>red</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>Joe</th>\n      <td>0.503905</td>\n      <td>1.063885</td>\n    </tr>\n    <tr>\n      <th>Steve</th>\n      <td>1.297183</td>\n      <td>-1.553778</td>\n    </tr>\n    <tr>\n      <th>Wes</th>\n      <td>-1.021228</td>\n      <td>-1.116829</td>\n    </tr>\n    <tr>\n      <th>Jim</th>\n      <td>0.524712</td>\n      <td>1.770545</td>\n    </tr>\n    <tr>\n      <th>Travis</th>\n      <td>-4.230992</td>\n      <td>-2.405455</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mapping = {'a': 'red', 'b': 'red', 'c': 'blue', 'd': 'blue', 'e': 'red', 'f': 'orange'}\n",
    "by_column = people.groupby(mapping, axis=1)\n",
    "by_column.sum()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.230037Z",
     "end_time": "2024-04-24T20:22:09.541264Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "data": {
      "text/plain": "a       red\nb       red\nc      blue\nd      blue\ne       red\nf    orange\ndtype: object"
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map_series = pd.Series(mapping)\n",
    "map_series"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.245267Z",
     "end_time": "2024-04-24T20:22:09.578130Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\1366557749.py:1: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.\n",
      "  people.groupby(map_series, axis=1).count()\n"
     ]
    },
    {
     "data": {
      "text/plain": "        blue  red\nJoe        2    3\nSteve      2    3\nWes        1    2\nJim        2    3\nTravis     2    3",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>blue</th>\n      <th>red</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>Joe</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>Steve</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>Wes</th>\n      <td>1</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>Jim</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>Travis</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "people.groupby(map_series, axis=1).count()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.271006Z",
     "end_time": "2024-04-24T20:22:09.578130Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 通过函数进行分组"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "data": {
      "text/plain": "          a         b         c         d         e\n3  0.591569 -0.993608  0.798764 -0.791374  2.119639\n5  0.886429 -2.001637 -0.371843  1.669025 -0.438570\n6 -0.713544 -0.831154 -2.370232 -1.860761 -0.860757",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>a</th>\n      <th>b</th>\n      <th>c</th>\n      <th>d</th>\n      <th>e</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>3</th>\n      <td>0.591569</td>\n      <td>-0.993608</td>\n      <td>0.798764</td>\n      <td>-0.791374</td>\n      <td>2.119639</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <td>0.886429</td>\n      <td>-2.001637</td>\n      <td>-0.371843</td>\n      <td>1.669025</td>\n      <td>-0.438570</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <td>-0.713544</td>\n      <td>-0.831154</td>\n      <td>-2.370232</td>\n      <td>-1.860761</td>\n      <td>-0.860757</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "people.groupby(len).sum()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.299213Z",
     "end_time": "2024-04-24T20:22:09.578130Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [
    {
     "data": {
      "text/plain": "              a         b         c         d         e\n3 one -0.539741 -1.296221  0.274992 -1.021228 -0.577087\n  two  0.124121  0.302614  0.523772  0.000940  1.343810\n5 one  0.886429 -2.001637 -0.371843  1.669025 -0.438570\n6 two -0.713544 -0.831154 -2.370232 -1.860761 -0.860757",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>a</th>\n      <th>b</th>\n      <th>c</th>\n      <th>d</th>\n      <th>e</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">3</th>\n      <th>one</th>\n      <td>-0.539741</td>\n      <td>-1.296221</td>\n      <td>0.274992</td>\n      <td>-1.021228</td>\n      <td>-0.577087</td>\n    </tr>\n    <tr>\n      <th>two</th>\n      <td>0.124121</td>\n      <td>0.302614</td>\n      <td>0.523772</td>\n      <td>0.000940</td>\n      <td>1.343810</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <th>one</th>\n      <td>0.886429</td>\n      <td>-2.001637</td>\n      <td>-0.371843</td>\n      <td>1.669025</td>\n      <td>-0.438570</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <th>two</th>\n      <td>-0.713544</td>\n      <td>-0.831154</td>\n      <td>-2.370232</td>\n      <td>-1.860761</td>\n      <td>-0.860757</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "key_list = ['one', 'one', 'one', 'two', 'two']\n",
    "people.groupby([len, key_list]).min()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.318555Z",
     "end_time": "2024-04-24T20:22:09.725291Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 根据索引级别分组"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "data": {
      "text/plain": "cty          US                            JP          \ntenor         1         3         5         1         3\n0      0.560145 -1.265934  0.119827 -1.063512  0.332883\n1     -2.359419 -0.199543 -1.541996 -0.970736 -1.307030\n2      0.286350  0.377984 -0.753887  0.331286  1.349742\n3      0.069877  0.246674 -0.011862  1.004812  1.327195",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th>cty</th>\n      <th colspan=\"3\" halign=\"left\">US</th>\n      <th colspan=\"2\" halign=\"left\">JP</th>\n    </tr>\n    <tr>\n      <th>tenor</th>\n      <th>1</th>\n      <th>3</th>\n      <th>5</th>\n      <th>1</th>\n      <th>3</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>0.560145</td>\n      <td>-1.265934</td>\n      <td>0.119827</td>\n      <td>-1.063512</td>\n      <td>0.332883</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>-2.359419</td>\n      <td>-0.199543</td>\n      <td>-1.541996</td>\n      <td>-0.970736</td>\n      <td>-1.307030</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>0.286350</td>\n      <td>0.377984</td>\n      <td>-0.753887</td>\n      <td>0.331286</td>\n      <td>1.349742</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>0.069877</td>\n      <td>0.246674</td>\n      <td>-0.011862</td>\n      <td>1.004812</td>\n      <td>1.327195</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "columns = pd.MultiIndex.from_arrays([[\"US\", \"US\", \"US\", \"JP\", \"JP\"],\n",
    "                                     [1, 3, 5, 1, 3]],\n",
    "                                    names=[\"cty\", \"tenor\"])\n",
    "hier_df = pd.DataFrame(np.random.standard_normal((4, 5)), columns=columns)\n",
    "hier_df"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.353573Z",
     "end_time": "2024-04-24T20:22:09.725291Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\2253353235.py:1: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.\n",
      "  hier_df.groupby(level=\"cty\", axis=\"columns\").count()\n"
     ]
    },
    {
     "data": {
      "text/plain": "cty  JP  US\n0     2   3\n1     2   3\n2     2   3\n3     2   3",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th>cty</th>\n      <th>JP</th>\n      <th>US</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>2</td>\n      <td>3</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hier_df.groupby(level=\"cty\", axis=\"columns\").count()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.366675Z",
     "end_time": "2024-04-24T20:22:09.725291Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 10.2 数据聚合"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "data": {
      "text/plain": "  key1 key2     data1     data2\n0    a  one -0.204708  1.393406\n1    a  two  0.478943  0.092908\n2    b  one -0.519439  0.281746\n3    b  two -0.555730  0.769023\n4    a  one  1.965781  1.246435",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>key1</th>\n      <th>key2</th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>a</td>\n      <td>one</td>\n      <td>-0.204708</td>\n      <td>1.393406</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>a</td>\n      <td>two</td>\n      <td>0.478943</td>\n      <td>0.092908</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>b</td>\n      <td>one</td>\n      <td>-0.519439</td>\n      <td>0.281746</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>b</td>\n      <td>two</td>\n      <td>-0.555730</td>\n      <td>0.769023</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>a</td>\n      <td>one</td>\n      <td>1.965781</td>\n      <td>1.246435</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.398969Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "data": {
      "text/plain": "key1\na    1.668413\nb   -0.523068\nName: data1, dtype: float64"
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped = df.groupby('key1')\n",
    "grouped['data1'].quantile(0.9)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.427395Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "outputs": [],
   "source": [
    "def peak_to_peak(arr):\n",
    "    return arr.max() - arr.min()\n",
    "\n",
    "#grouped.agg(peak_to_peak)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.441435Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "outputs": [
    {
     "data": {
      "text/plain": "     data1                                                              \\\n     count      mean       std       min       25%       50%       75%   \nkey1                                                                     \na      3.0  0.746672  1.109736 -0.204708  0.137118  0.478943  1.222362   \nb      2.0 -0.537585  0.025662 -0.555730 -0.546657 -0.537585 -0.528512   \n\n               data2                                                    \\\n           max count      mean       std       min       25%       50%   \nkey1                                                                     \na     1.965781   3.0  0.910916  0.712217  0.092908  0.669671  1.246435   \nb    -0.519439   2.0  0.525384  0.344556  0.281746  0.403565  0.525384   \n\n                          \n           75%       max  \nkey1                      \na     1.319920  1.393406  \nb     0.647203  0.769023  ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th colspan=\"8\" halign=\"left\">data1</th>\n      <th colspan=\"8\" halign=\"left\">data2</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th>count</th>\n      <th>mean</th>\n      <th>std</th>\n      <th>min</th>\n      <th>25%</th>\n      <th>50%</th>\n      <th>75%</th>\n      <th>max</th>\n      <th>count</th>\n      <th>mean</th>\n      <th>std</th>\n      <th>min</th>\n      <th>25%</th>\n      <th>50%</th>\n      <th>75%</th>\n      <th>max</th>\n    </tr>\n    <tr>\n      <th>key1</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>a</th>\n      <td>3.0</td>\n      <td>0.746672</td>\n      <td>1.109736</td>\n      <td>-0.204708</td>\n      <td>0.137118</td>\n      <td>0.478943</td>\n      <td>1.222362</td>\n      <td>1.965781</td>\n      <td>3.0</td>\n      <td>0.910916</td>\n      <td>0.712217</td>\n      <td>0.092908</td>\n      <td>0.669671</td>\n      <td>1.246435</td>\n      <td>1.319920</td>\n      <td>1.393406</td>\n    </tr>\n    <tr>\n      <th>b</th>\n      <td>2.0</td>\n      <td>-0.537585</td>\n      <td>0.025662</td>\n      <td>-0.555730</td>\n      <td>-0.546657</td>\n      <td>-0.537585</td>\n      <td>-0.528512</td>\n      <td>-0.519439</td>\n      <td>2.0</td>\n      <td>0.525384</td>\n      <td>0.344556</td>\n      <td>0.281746</td>\n      <td>0.403565</td>\n      <td>0.525384</td>\n      <td>0.647203</td>\n      <td>0.769023</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped.describe()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.461571Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 面向列的多函数应用"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "data": {
      "text/plain": "   total_bill   tip smoker  day    time  size\n0       16.99  1.01     No  Sun  Dinner     2\n1       10.34  1.66     No  Sun  Dinner     3\n2       21.01  3.50     No  Sun  Dinner     3\n3       23.68  3.31     No  Sun  Dinner     2\n4       24.59  3.61     No  Sun  Dinner     4",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>16.99</td>\n      <td>1.01</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>10.34</td>\n      <td>1.66</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>21.01</td>\n      <td>3.50</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>23.68</td>\n      <td>3.31</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>24.59</td>\n      <td>3.61</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>4</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips = pd.read_csv(\"examples/tips.csv\")\n",
    "tips.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.487794Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "outputs": [
    {
     "data": {
      "text/plain": "   total_bill   tip smoker  day    time  size   tip_pct\n0       16.99  1.01     No  Sun  Dinner     2  0.059447\n1       10.34  1.66     No  Sun  Dinner     3  0.160542\n2       21.01  3.50     No  Sun  Dinner     3  0.166587\n3       23.68  3.31     No  Sun  Dinner     2  0.139780\n4       24.59  3.61     No  Sun  Dinner     4  0.146808",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>16.99</td>\n      <td>1.01</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.059447</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>10.34</td>\n      <td>1.66</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n      <td>0.160542</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>21.01</td>\n      <td>3.50</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n      <td>0.166587</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>23.68</td>\n      <td>3.31</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.139780</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>24.59</td>\n      <td>3.61</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.146808</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips[\"tip_pct\"] = tips[\"tip\"] / tips[\"total_bill\"]\n",
    "tips.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.504104Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "outputs": [
    {
     "data": {
      "text/plain": "day   smoker\nFri   No        0.151650\n      Yes       0.174783\nSat   No        0.158048\n      Yes       0.147906\nSun   No        0.160113\n      Yes       0.187250\nThur  No        0.160298\n      Yes       0.163863\nName: tip_pct, dtype: float64"
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped = tips.groupby([\"day\", \"smoker\"])\n",
    "grouped_pct = grouped[\"tip_pct\"]\n",
    "grouped_pct.agg(\"mean\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.520422Z",
     "end_time": "2024-04-24T20:22:09.729204Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "outputs": [
    {
     "data": {
      "text/plain": "                 mean       std  peak_to_peak\nday  smoker                                  \nFri  No      0.151650  0.028123      0.067349\n     Yes     0.174783  0.051293      0.159925\nSat  No      0.158048  0.039767      0.235193\n     Yes     0.147906  0.061375      0.290095\nSun  No      0.160113  0.042347      0.193226\n     Yes     0.187250  0.154134      0.644685\nThur No      0.160298  0.038774      0.193350\n     Yes     0.163863  0.039389      0.151240",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>mean</th>\n      <th>std</th>\n      <th>peak_to_peak</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>0.151650</td>\n      <td>0.028123</td>\n      <td>0.067349</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.174783</td>\n      <td>0.051293</td>\n      <td>0.159925</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>0.158048</td>\n      <td>0.039767</td>\n      <td>0.235193</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.147906</td>\n      <td>0.061375</td>\n      <td>0.290095</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>0.160113</td>\n      <td>0.042347</td>\n      <td>0.193226</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.187250</td>\n      <td>0.154134</td>\n      <td>0.644685</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>0.160298</td>\n      <td>0.038774</td>\n      <td>0.193350</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.163863</td>\n      <td>0.039389</td>\n      <td>0.151240</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped_pct.agg([\"mean\", \"std\", peak_to_peak])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.541264Z",
     "end_time": "2024-04-24T20:22:09.785092Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\292991792.py:1: FutureWarning: The provided callable <function std at 0x00000238AA2E1900> is currently using SeriesGroupBy.std. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"std\" instead.\n",
      "  grouped_pct.agg([('foo', 'mean'), ('bar', np.std)])\n"
     ]
    },
    {
     "data": {
      "text/plain": "                  foo       bar\nday  smoker                    \nFri  No      0.151650  0.028123\n     Yes     0.174783  0.051293\nSat  No      0.158048  0.039767\n     Yes     0.147906  0.061375\nSun  No      0.160113  0.042347\n     Yes     0.187250  0.154134\nThur No      0.160298  0.038774\n     Yes     0.163863  0.039389",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>foo</th>\n      <th>bar</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>0.151650</td>\n      <td>0.028123</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.174783</td>\n      <td>0.051293</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>0.158048</td>\n      <td>0.039767</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.147906</td>\n      <td>0.061375</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>0.160113</td>\n      <td>0.042347</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.187250</td>\n      <td>0.154134</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>0.160298</td>\n      <td>0.038774</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.163863</td>\n      <td>0.039389</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped_pct.agg([('foo', 'mean'), ('bar', np.std)])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.557440Z",
     "end_time": "2024-04-24T20:22:09.825080Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\3111280939.py:1: FutureWarning: The provided callable <function std at 0x00000238AA2E1900> is currently using SeriesGroupBy.std. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"std\" instead.\n",
      "  grouped_pct.agg([(\"average\", \"mean\"), (\"stdev\", np.std)])\n"
     ]
    },
    {
     "data": {
      "text/plain": "              average     stdev\nday  smoker                    \nFri  No      0.151650  0.028123\n     Yes     0.174783  0.051293\nSat  No      0.158048  0.039767\n     Yes     0.147906  0.061375\nSun  No      0.160113  0.042347\n     Yes     0.187250  0.154134\nThur No      0.160298  0.038774\n     Yes     0.163863  0.039389",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>average</th>\n      <th>stdev</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>0.151650</td>\n      <td>0.028123</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.174783</td>\n      <td>0.051293</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>0.158048</td>\n      <td>0.039767</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.147906</td>\n      <td>0.061375</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>0.160113</td>\n      <td>0.042347</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.187250</td>\n      <td>0.154134</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>0.160298</td>\n      <td>0.038774</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.163863</td>\n      <td>0.039389</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped_pct.agg([(\"average\", \"mean\"), (\"stdev\", np.std)])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.573789Z",
     "end_time": "2024-04-24T20:22:09.826570Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "outputs": [
    {
     "data": {
      "text/plain": "            tip_pct                     total_bill                  \n              count      mean       max      count       mean    max\nday  smoker                                                         \nFri  No           4  0.151650  0.187735          4  18.420000  22.75\n     Yes         15  0.174783  0.263480         15  16.813333  40.17\nSat  No          45  0.158048  0.291990         45  19.661778  48.33\n     Yes         42  0.147906  0.325733         42  21.276667  50.81\nSun  No          57  0.160113  0.252672         57  20.506667  48.17\n     Yes         19  0.187250  0.710345         19  24.120000  45.35\nThur No          45  0.160298  0.266312         45  17.113111  41.19\n     Yes         17  0.163863  0.241255         17  19.190588  43.11",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th></th>\n      <th colspan=\"3\" halign=\"left\">tip_pct</th>\n      <th colspan=\"3\" halign=\"left\">total_bill</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th></th>\n      <th>count</th>\n      <th>mean</th>\n      <th>max</th>\n      <th>count</th>\n      <th>mean</th>\n      <th>max</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>4</td>\n      <td>0.151650</td>\n      <td>0.187735</td>\n      <td>4</td>\n      <td>18.420000</td>\n      <td>22.75</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>15</td>\n      <td>0.174783</td>\n      <td>0.263480</td>\n      <td>15</td>\n      <td>16.813333</td>\n      <td>40.17</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>45</td>\n      <td>0.158048</td>\n      <td>0.291990</td>\n      <td>45</td>\n      <td>19.661778</td>\n      <td>48.33</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>42</td>\n      <td>0.147906</td>\n      <td>0.325733</td>\n      <td>42</td>\n      <td>21.276667</td>\n      <td>50.81</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>57</td>\n      <td>0.160113</td>\n      <td>0.252672</td>\n      <td>57</td>\n      <td>20.506667</td>\n      <td>48.17</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>19</td>\n      <td>0.187250</td>\n      <td>0.710345</td>\n      <td>19</td>\n      <td>24.120000</td>\n      <td>45.35</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>45</td>\n      <td>0.160298</td>\n      <td>0.266312</td>\n      <td>45</td>\n      <td>17.113111</td>\n      <td>41.19</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>17</td>\n      <td>0.163863</td>\n      <td>0.241255</td>\n      <td>17</td>\n      <td>19.190588</td>\n      <td>43.11</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "functions = [\"count\", \"mean\", \"max\"]\n",
    "result = grouped[[\"tip_pct\", \"total_bill\"]].agg(functions)\n",
    "result"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.597614Z",
     "end_time": "2024-04-24T20:22:09.832081Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "outputs": [
    {
     "data": {
      "text/plain": "             count      mean       max\nday  smoker                           \nFri  No          4  0.151650  0.187735\n     Yes        15  0.174783  0.263480\nSat  No         45  0.158048  0.291990\n     Yes        42  0.147906  0.325733\nSun  No         57  0.160113  0.252672\n     Yes        19  0.187250  0.710345\nThur No         45  0.160298  0.266312\n     Yes        17  0.163863  0.241255",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>count</th>\n      <th>mean</th>\n      <th>max</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>4</td>\n      <td>0.151650</td>\n      <td>0.187735</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>15</td>\n      <td>0.174783</td>\n      <td>0.263480</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>45</td>\n      <td>0.158048</td>\n      <td>0.291990</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>42</td>\n      <td>0.147906</td>\n      <td>0.325733</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>57</td>\n      <td>0.160113</td>\n      <td>0.252672</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>19</td>\n      <td>0.187250</td>\n      <td>0.710345</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>45</td>\n      <td>0.160298</td>\n      <td>0.266312</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>17</td>\n      <td>0.163863</td>\n      <td>0.241255</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result['tip_pct']"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.618609Z",
     "end_time": "2024-04-24T20:22:09.867167Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\2169842100.py:2: FutureWarning: The provided callable <function var at 0x00000238AA2E1A20> is currently using SeriesGroupBy.var. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"var\" instead.\n",
      "  grouped[[\"tip_pct\", \"total_bill\"]].agg(ftuples)\n"
     ]
    },
    {
     "data": {
      "text/plain": "              tip_pct           total_bill            \n              Average  Variance    Average    Variance\nday  smoker                                           \nFri  No      0.151650  0.000791  18.420000   25.596333\n     Yes     0.174783  0.002631  16.813333   82.562438\nSat  No      0.158048  0.001581  19.661778   79.908965\n     Yes     0.147906  0.003767  21.276667  101.387535\nSun  No      0.160113  0.001793  20.506667   66.099980\n     Yes     0.187250  0.023757  24.120000  109.046044\nThur No      0.160298  0.001503  17.113111   59.625081\n     Yes     0.163863  0.001551  19.190588   69.808518",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th></th>\n      <th colspan=\"2\" halign=\"left\">tip_pct</th>\n      <th colspan=\"2\" halign=\"left\">total_bill</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th></th>\n      <th>Average</th>\n      <th>Variance</th>\n      <th>Average</th>\n      <th>Variance</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>0.151650</td>\n      <td>0.000791</td>\n      <td>18.420000</td>\n      <td>25.596333</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.174783</td>\n      <td>0.002631</td>\n      <td>16.813333</td>\n      <td>82.562438</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>0.158048</td>\n      <td>0.001581</td>\n      <td>19.661778</td>\n      <td>79.908965</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.147906</td>\n      <td>0.003767</td>\n      <td>21.276667</td>\n      <td>101.387535</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>0.160113</td>\n      <td>0.001793</td>\n      <td>20.506667</td>\n      <td>66.099980</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.187250</td>\n      <td>0.023757</td>\n      <td>24.120000</td>\n      <td>109.046044</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>0.160298</td>\n      <td>0.001503</td>\n      <td>17.113111</td>\n      <td>59.625081</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.163863</td>\n      <td>0.001551</td>\n      <td>19.190588</td>\n      <td>69.808518</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ftuples = [(\"Average\", \"mean\"), (\"Variance\", np.var)]\n",
    "grouped[[\"tip_pct\", \"total_bill\"]].agg(ftuples)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.649201Z",
     "end_time": "2024-04-24T20:22:09.941589Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\727700194.py:1: FutureWarning: The provided callable <function max at 0x00000238AA2E0EE0> is currently using SeriesGroupBy.max. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"max\" instead.\n",
      "  grouped.agg({\"tip\": np.max, \"size\": \"sum\"})\n"
     ]
    },
    {
     "data": {
      "text/plain": "               tip  size\nday  smoker             \nFri  No       3.50     9\n     Yes      4.73    31\nSat  No       9.00   115\n     Yes     10.00   104\nSun  No       6.00   167\n     Yes      6.50    49\nThur No       6.70   112\n     Yes      5.00    40",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>tip</th>\n      <th>size</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>3.50</td>\n      <td>9</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>4.73</td>\n      <td>31</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>9.00</td>\n      <td>115</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>10.00</td>\n      <td>104</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>6.00</td>\n      <td>167</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>6.50</td>\n      <td>49</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>6.70</td>\n      <td>112</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>5.00</td>\n      <td>40</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped.agg({\"tip\": np.max, \"size\": \"sum\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.666324Z",
     "end_time": "2024-04-24T20:22:10.018924Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "outputs": [
    {
     "data": {
      "text/plain": "              tip_pct                               size\n                  min       max      mean       std  sum\nday  smoker                                             \nFri  No      0.120385  0.187735  0.151650  0.028123    9\n     Yes     0.103555  0.263480  0.174783  0.051293   31\nSat  No      0.056797  0.291990  0.158048  0.039767  115\n     Yes     0.035638  0.325733  0.147906  0.061375  104\nSun  No      0.059447  0.252672  0.160113  0.042347  167\n     Yes     0.065660  0.710345  0.187250  0.154134   49\nThur No      0.072961  0.266312  0.160298  0.038774  112\n     Yes     0.090014  0.241255  0.163863  0.039389   40",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th></th>\n      <th colspan=\"4\" halign=\"left\">tip_pct</th>\n      <th>size</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th></th>\n      <th>min</th>\n      <th>max</th>\n      <th>mean</th>\n      <th>std</th>\n      <th>sum</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>0.120385</td>\n      <td>0.187735</td>\n      <td>0.151650</td>\n      <td>0.028123</td>\n      <td>9</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.103555</td>\n      <td>0.263480</td>\n      <td>0.174783</td>\n      <td>0.051293</td>\n      <td>31</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>0.056797</td>\n      <td>0.291990</td>\n      <td>0.158048</td>\n      <td>0.039767</td>\n      <td>115</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.035638</td>\n      <td>0.325733</td>\n      <td>0.147906</td>\n      <td>0.061375</td>\n      <td>104</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>0.059447</td>\n      <td>0.252672</td>\n      <td>0.160113</td>\n      <td>0.042347</td>\n      <td>167</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.065660</td>\n      <td>0.710345</td>\n      <td>0.187250</td>\n      <td>0.154134</td>\n      <td>49</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>0.072961</td>\n      <td>0.266312</td>\n      <td>0.160298</td>\n      <td>0.038774</td>\n      <td>112</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.090014</td>\n      <td>0.241255</td>\n      <td>0.163863</td>\n      <td>0.039389</td>\n      <td>40</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped.agg({\"tip_pct\": [\"min\", \"max\", \"mean\", \"std\"],\n",
    "             \"size\": \"sum\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.687006Z",
     "end_time": "2024-04-24T20:22:10.086121Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 以“没有行索引”的形式返回聚合数据"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "outputs": [
    {
     "data": {
      "text/plain": "    day smoker  total_bill       tip      size   tip_pct\n0   Fri     No   18.420000  2.812500  2.250000  0.151650\n1   Fri    Yes   16.813333  2.714000  2.066667  0.174783\n2   Sat     No   19.661778  3.102889  2.555556  0.158048\n3   Sat    Yes   21.276667  2.875476  2.476190  0.147906\n4   Sun     No   20.506667  3.167895  2.929825  0.160113\n5   Sun    Yes   24.120000  3.516842  2.578947  0.187250\n6  Thur     No   17.113111  2.673778  2.488889  0.160298\n7  Thur    Yes   19.190588  3.030000  2.352941  0.163863",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>day</th>\n      <th>smoker</th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>Fri</td>\n      <td>No</td>\n      <td>18.420000</td>\n      <td>2.812500</td>\n      <td>2.250000</td>\n      <td>0.151650</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>Fri</td>\n      <td>Yes</td>\n      <td>16.813333</td>\n      <td>2.714000</td>\n      <td>2.066667</td>\n      <td>0.174783</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>Sat</td>\n      <td>No</td>\n      <td>19.661778</td>\n      <td>3.102889</td>\n      <td>2.555556</td>\n      <td>0.158048</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>Sat</td>\n      <td>Yes</td>\n      <td>21.276667</td>\n      <td>2.875476</td>\n      <td>2.476190</td>\n      <td>0.147906</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>Sun</td>\n      <td>No</td>\n      <td>20.506667</td>\n      <td>3.167895</td>\n      <td>2.929825</td>\n      <td>0.160113</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <td>Sun</td>\n      <td>Yes</td>\n      <td>24.120000</td>\n      <td>3.516842</td>\n      <td>2.578947</td>\n      <td>0.187250</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <td>Thur</td>\n      <td>No</td>\n      <td>17.113111</td>\n      <td>2.673778</td>\n      <td>2.488889</td>\n      <td>0.160298</td>\n    </tr>\n    <tr>\n      <th>7</th>\n      <td>Thur</td>\n      <td>Yes</td>\n      <td>19.190588</td>\n      <td>3.030000</td>\n      <td>2.352941</td>\n      <td>0.163863</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped = tips.groupby([\"day\", \"smoker\"], as_index=False)\n",
    "grouped.mean(numeric_only=True)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.703211Z",
     "end_time": "2024-04-24T20:22:10.086121Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 10.3 apply:一般性的“拆分 - 应用 - 合并”"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "outputs": [
    {
     "data": {
      "text/plain": "     total_bill   tip smoker  day    time  size   tip_pct\n172        7.25  5.15    Yes  Sun  Dinner     2  0.710345\n178        9.60  4.00    Yes  Sun  Dinner     2  0.416667\n67         3.07  1.00    Yes  Sat  Dinner     1  0.325733\n232       11.61  3.39     No  Sat  Dinner     2  0.291990\n183       23.17  6.50    Yes  Sun  Dinner     4  0.280535\n109       14.31  4.00    Yes  Sat  Dinner     2  0.279525",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>172</th>\n      <td>7.25</td>\n      <td>5.15</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.710345</td>\n    </tr>\n    <tr>\n      <th>178</th>\n      <td>9.60</td>\n      <td>4.00</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.416667</td>\n    </tr>\n    <tr>\n      <th>67</th>\n      <td>3.07</td>\n      <td>1.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>1</td>\n      <td>0.325733</td>\n    </tr>\n    <tr>\n      <th>232</th>\n      <td>11.61</td>\n      <td>3.39</td>\n      <td>No</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.291990</td>\n    </tr>\n    <tr>\n      <th>183</th>\n      <td>23.17</td>\n      <td>6.50</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.280535</td>\n    </tr>\n    <tr>\n      <th>109</th>\n      <td>14.31</td>\n      <td>4.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.279525</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def top(df, n=5, column=\"tip_pct\"):\n",
    "    return df.sort_values(column, ascending=False)[:n]\n",
    "\n",
    "\n",
    "top(tips, n=6)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.728708Z",
     "end_time": "2024-04-24T20:22:10.086121Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "outputs": [
    {
     "data": {
      "text/plain": "            total_bill   tip smoker   day    time  size   tip_pct\nsmoker                                                           \nNo     232       11.61  3.39     No   Sat  Dinner     2  0.291990\n       149        7.51  2.00     No  Thur   Lunch     2  0.266312\n       51        10.29  2.60     No   Sun  Dinner     2  0.252672\n       185       20.69  5.00     No   Sun  Dinner     5  0.241663\n       88        24.71  5.85     No  Thur   Lunch     2  0.236746\nYes    172        7.25  5.15    Yes   Sun  Dinner     2  0.710345\n       178        9.60  4.00    Yes   Sun  Dinner     2  0.416667\n       67         3.07  1.00    Yes   Sat  Dinner     1  0.325733\n       183       23.17  6.50    Yes   Sun  Dinner     4  0.280535\n       109       14.31  4.00    Yes   Sat  Dinner     2  0.279525",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n    <tr>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"5\" valign=\"top\">No</th>\n      <th>232</th>\n      <td>11.61</td>\n      <td>3.39</td>\n      <td>No</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.291990</td>\n    </tr>\n    <tr>\n      <th>149</th>\n      <td>7.51</td>\n      <td>2.00</td>\n      <td>No</td>\n      <td>Thur</td>\n      <td>Lunch</td>\n      <td>2</td>\n      <td>0.266312</td>\n    </tr>\n    <tr>\n      <th>51</th>\n      <td>10.29</td>\n      <td>2.60</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.252672</td>\n    </tr>\n    <tr>\n      <th>185</th>\n      <td>20.69</td>\n      <td>5.00</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>5</td>\n      <td>0.241663</td>\n    </tr>\n    <tr>\n      <th>88</th>\n      <td>24.71</td>\n      <td>5.85</td>\n      <td>No</td>\n      <td>Thur</td>\n      <td>Lunch</td>\n      <td>2</td>\n      <td>0.236746</td>\n    </tr>\n    <tr>\n      <th rowspan=\"5\" valign=\"top\">Yes</th>\n      <th>172</th>\n      <td>7.25</td>\n      <td>5.15</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.710345</td>\n    </tr>\n    <tr>\n      <th>178</th>\n      <td>9.60</td>\n      <td>4.00</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.416667</td>\n    </tr>\n    <tr>\n      <th>67</th>\n      <td>3.07</td>\n      <td>1.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>1</td>\n      <td>0.325733</td>\n    </tr>\n    <tr>\n      <th>183</th>\n      <td>23.17</td>\n      <td>6.50</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.280535</td>\n    </tr>\n    <tr>\n      <th>109</th>\n      <td>14.31</td>\n      <td>4.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.279525</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.groupby(\"smoker\").apply(top)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.745693Z",
     "end_time": "2024-04-24T20:22:10.288084Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "outputs": [
    {
     "data": {
      "text/plain": "                 total_bill    tip smoker   day    time  size   tip_pct\nsmoker day                                                             \nNo     Fri  94        22.75   3.25     No   Fri  Dinner     2  0.142857\n       Sat  212       48.33   9.00     No   Sat  Dinner     4  0.186220\n       Sun  156       48.17   5.00     No   Sun  Dinner     6  0.103799\n       Thur 142       41.19   5.00     No  Thur   Lunch     5  0.121389\nYes    Fri  95        40.17   4.73    Yes   Fri  Dinner     4  0.117750\n       Sat  170       50.81  10.00    Yes   Sat  Dinner     3  0.196812\n       Sun  182       45.35   3.50    Yes   Sun  Dinner     3  0.077178\n       Thur 197       43.11   5.00    Yes  Thur   Lunch     4  0.115982",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n    <tr>\n      <th>smoker</th>\n      <th>day</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"4\" valign=\"top\">No</th>\n      <th>Fri</th>\n      <th>94</th>\n      <td>22.75</td>\n      <td>3.25</td>\n      <td>No</td>\n      <td>Fri</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.142857</td>\n    </tr>\n    <tr>\n      <th>Sat</th>\n      <th>212</th>\n      <td>48.33</td>\n      <td>9.00</td>\n      <td>No</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.186220</td>\n    </tr>\n    <tr>\n      <th>Sun</th>\n      <th>156</th>\n      <td>48.17</td>\n      <td>5.00</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>6</td>\n      <td>0.103799</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <th>142</th>\n      <td>41.19</td>\n      <td>5.00</td>\n      <td>No</td>\n      <td>Thur</td>\n      <td>Lunch</td>\n      <td>5</td>\n      <td>0.121389</td>\n    </tr>\n    <tr>\n      <th rowspan=\"4\" valign=\"top\">Yes</th>\n      <th>Fri</th>\n      <th>95</th>\n      <td>40.17</td>\n      <td>4.73</td>\n      <td>Yes</td>\n      <td>Fri</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.117750</td>\n    </tr>\n    <tr>\n      <th>Sat</th>\n      <th>170</th>\n      <td>50.81</td>\n      <td>10.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>3</td>\n      <td>0.196812</td>\n    </tr>\n    <tr>\n      <th>Sun</th>\n      <th>182</th>\n      <td>45.35</td>\n      <td>3.50</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n      <td>0.077178</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <th>197</th>\n      <td>43.11</td>\n      <td>5.00</td>\n      <td>Yes</td>\n      <td>Thur</td>\n      <td>Lunch</td>\n      <td>4</td>\n      <td>0.115982</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.groupby([\"smoker\", \"day\"]).apply(top, n=1, column=\"total_bill\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.765129Z",
     "end_time": "2024-04-24T20:22:10.289072Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "outputs": [
    {
     "data": {
      "text/plain": "        count      mean       std       min       25%       50%       75%  \\\nsmoker                                                                      \nNo      151.0  0.159328  0.039910  0.056797  0.136906  0.155625  0.185014   \nYes      93.0  0.163196  0.085119  0.035638  0.106771  0.153846  0.195059   \n\n             max  \nsmoker            \nNo      0.291990  \nYes     0.710345  ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>count</th>\n      <th>mean</th>\n      <th>std</th>\n      <th>min</th>\n      <th>25%</th>\n      <th>50%</th>\n      <th>75%</th>\n      <th>max</th>\n    </tr>\n    <tr>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>No</th>\n      <td>151.0</td>\n      <td>0.159328</td>\n      <td>0.039910</td>\n      <td>0.056797</td>\n      <td>0.136906</td>\n      <td>0.155625</td>\n      <td>0.185014</td>\n      <td>0.291990</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>93.0</td>\n      <td>0.163196</td>\n      <td>0.085119</td>\n      <td>0.035638</td>\n      <td>0.106771</td>\n      <td>0.153846</td>\n      <td>0.195059</td>\n      <td>0.710345</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = tips.groupby(\"smoker\")[\"tip_pct\"].describe()\n",
    "result"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.790325Z",
     "end_time": "2024-04-24T20:22:10.289568Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "outputs": [
    {
     "data": {
      "text/plain": "       smoker\ncount  No        151.000000\n       Yes        93.000000\nmean   No          0.159328\n       Yes         0.163196\nstd    No          0.039910\n       Yes         0.085119\nmin    No          0.056797\n       Yes         0.035638\n25%    No          0.136906\n       Yes         0.106771\n50%    No          0.155625\n       Yes         0.153846\n75%    No          0.185014\n       Yes         0.195059\nmax    No          0.291990\n       Yes         0.710345\ndtype: float64"
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result.unstack(\"smoker\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.824086Z",
     "end_time": "2024-04-24T20:22:10.335287Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "outputs": [
    {
     "data": {
      "text/plain": "         total_bill       tip  size   tip_pct\n0 count    4.000000  4.000000  4.00  4.000000\n  mean    18.420000  2.812500  2.25  0.151650\n  std      5.059282  0.898494  0.50  0.028123\n  min     12.460000  1.500000  2.00  0.120385\n  25%     15.100000  2.625000  2.00  0.137239\n...             ...       ...   ...       ...\n7 min     10.340000  2.000000  2.00  0.090014\n  25%     13.510000  2.000000  2.00  0.148038\n  50%     16.470000  2.560000  2.00  0.153846\n  75%     19.810000  4.000000  2.00  0.194837\n  max     43.110000  5.000000  4.00  0.241255\n\n[64 rows x 4 columns]",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"5\" valign=\"top\">0</th>\n      <th>count</th>\n      <td>4.000000</td>\n      <td>4.000000</td>\n      <td>4.00</td>\n      <td>4.000000</td>\n    </tr>\n    <tr>\n      <th>mean</th>\n      <td>18.420000</td>\n      <td>2.812500</td>\n      <td>2.25</td>\n      <td>0.151650</td>\n    </tr>\n    <tr>\n      <th>std</th>\n      <td>5.059282</td>\n      <td>0.898494</td>\n      <td>0.50</td>\n      <td>0.028123</td>\n    </tr>\n    <tr>\n      <th>min</th>\n      <td>12.460000</td>\n      <td>1.500000</td>\n      <td>2.00</td>\n      <td>0.120385</td>\n    </tr>\n    <tr>\n      <th>25%</th>\n      <td>15.100000</td>\n      <td>2.625000</td>\n      <td>2.00</td>\n      <td>0.137239</td>\n    </tr>\n    <tr>\n      <th>...</th>\n      <th>...</th>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n    </tr>\n    <tr>\n      <th rowspan=\"5\" valign=\"top\">7</th>\n      <th>min</th>\n      <td>10.340000</td>\n      <td>2.000000</td>\n      <td>2.00</td>\n      <td>0.090014</td>\n    </tr>\n    <tr>\n      <th>25%</th>\n      <td>13.510000</td>\n      <td>2.000000</td>\n      <td>2.00</td>\n      <td>0.148038</td>\n    </tr>\n    <tr>\n      <th>50%</th>\n      <td>16.470000</td>\n      <td>2.560000</td>\n      <td>2.00</td>\n      <td>0.153846</td>\n    </tr>\n    <tr>\n      <th>75%</th>\n      <td>19.810000</td>\n      <td>4.000000</td>\n      <td>2.00</td>\n      <td>0.194837</td>\n    </tr>\n    <tr>\n      <th>max</th>\n      <td>43.110000</td>\n      <td>5.000000</td>\n      <td>4.00</td>\n      <td>0.241255</td>\n    </tr>\n  </tbody>\n</table>\n<p>64 rows × 4 columns</p>\n</div>"
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped.apply(lambda x: x.describe())"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.845162Z",
     "end_time": "2024-04-24T20:22:10.441993Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 禁止分组键"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "outputs": [
    {
     "data": {
      "text/plain": "     total_bill   tip smoker   day    time  size   tip_pct\n232       11.61  3.39     No   Sat  Dinner     2  0.291990\n149        7.51  2.00     No  Thur   Lunch     2  0.266312\n51        10.29  2.60     No   Sun  Dinner     2  0.252672\n185       20.69  5.00     No   Sun  Dinner     5  0.241663\n88        24.71  5.85     No  Thur   Lunch     2  0.236746\n172        7.25  5.15    Yes   Sun  Dinner     2  0.710345\n178        9.60  4.00    Yes   Sun  Dinner     2  0.416667\n67         3.07  1.00    Yes   Sat  Dinner     1  0.325733\n183       23.17  6.50    Yes   Sun  Dinner     4  0.280535\n109       14.31  4.00    Yes   Sat  Dinner     2  0.279525",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>232</th>\n      <td>11.61</td>\n      <td>3.39</td>\n      <td>No</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.291990</td>\n    </tr>\n    <tr>\n      <th>149</th>\n      <td>7.51</td>\n      <td>2.00</td>\n      <td>No</td>\n      <td>Thur</td>\n      <td>Lunch</td>\n      <td>2</td>\n      <td>0.266312</td>\n    </tr>\n    <tr>\n      <th>51</th>\n      <td>10.29</td>\n      <td>2.60</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.252672</td>\n    </tr>\n    <tr>\n      <th>185</th>\n      <td>20.69</td>\n      <td>5.00</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>5</td>\n      <td>0.241663</td>\n    </tr>\n    <tr>\n      <th>88</th>\n      <td>24.71</td>\n      <td>5.85</td>\n      <td>No</td>\n      <td>Thur</td>\n      <td>Lunch</td>\n      <td>2</td>\n      <td>0.236746</td>\n    </tr>\n    <tr>\n      <th>172</th>\n      <td>7.25</td>\n      <td>5.15</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.710345</td>\n    </tr>\n    <tr>\n      <th>178</th>\n      <td>9.60</td>\n      <td>4.00</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.416667</td>\n    </tr>\n    <tr>\n      <th>67</th>\n      <td>3.07</td>\n      <td>1.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>1</td>\n      <td>0.325733</td>\n    </tr>\n    <tr>\n      <th>183</th>\n      <td>23.17</td>\n      <td>6.50</td>\n      <td>Yes</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.280535</td>\n    </tr>\n    <tr>\n      <th>109</th>\n      <td>14.31</td>\n      <td>4.00</td>\n      <td>Yes</td>\n      <td>Sat</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.279525</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.groupby(\"smoker\", group_keys=False).apply(top)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.908648Z",
     "end_time": "2024-04-24T20:22:10.448336Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 分位数和桶分析"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "outputs": [
    {
     "data": {
      "text/plain": "      data1     data2\n0 -0.919262  1.165148\n1 -1.549106 -0.621249\n2  0.022185 -0.799318\n3  0.758363  0.777233\n4 -0.660524 -0.612905",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>-0.919262</td>\n      <td>1.165148</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>-1.549106</td>\n      <td>-0.621249</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>0.022185</td>\n      <td>-0.799318</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>0.758363</td>\n      <td>0.777233</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>-0.660524</td>\n      <td>-0.612905</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "frame = pd.DataFrame({\"data1\": np.random.standard_normal(1000),\n",
    "                      \"data2\": np.random.standard_normal(1000)})\n",
    "frame.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.940101Z",
     "end_time": "2024-04-24T20:22:10.470814Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "outputs": [
    {
     "data": {
      "text/plain": "0     (-1.23, 0.489]\n1    (-2.956, -1.23]\n2     (-1.23, 0.489]\n3     (0.489, 2.208]\n4     (-1.23, 0.489]\n5     (0.489, 2.208]\n6     (-1.23, 0.489]\n7     (-1.23, 0.489]\n8     (0.489, 2.208]\n9     (0.489, 2.208]\nName: data1, dtype: category\nCategories (4, interval[float64, right]): [(-2.956, -1.23] < (-1.23, 0.489] < (0.489, 2.208] < (2.208, 3.928]]"
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "quartiles = pd.cut(frame[\"data1\"], 4)\n",
    "quartiles.head(10)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.958290Z",
     "end_time": "2024-04-24T20:22:10.488064Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\58248\\AppData\\Local\\Temp\\ipykernel_15640\\512674978.py:8: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.\n",
      "  grouped = frame.groupby(quartiles)\n"
     ]
    },
    {
     "data": {
      "text/plain": "                      min                 max           count            mean  \\\n                    data1     data2     data1     data2 data1 data2     data1   \ndata1                                                                           \n(-2.956, -1.23] -2.949343 -3.399312 -1.230179  1.670835    95    95 -1.657663   \n(-1.23, 0.489]  -1.228918 -2.989741  0.488675  3.260383   598   598 -0.328648   \n(0.489, 2.208]   0.489965 -3.745356  2.200997  2.954439   297   297  1.065329   \n(2.208, 3.928]   2.212303 -1.929776  3.927528  1.765640    10    10  2.644253   \n\n                           \n                    data2  \ndata1                      \n(-2.956, -1.23] -0.039521  \n(-1.23, 0.489]  -0.002051  \n(0.489, 2.208]   0.081822  \n(2.208, 3.928]   0.024750  ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th colspan=\"2\" halign=\"left\">min</th>\n      <th colspan=\"2\" halign=\"left\">max</th>\n      <th colspan=\"2\" halign=\"left\">count</th>\n      <th colspan=\"2\" halign=\"left\">mean</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th>data1</th>\n      <th>data2</th>\n      <th>data1</th>\n      <th>data2</th>\n      <th>data1</th>\n      <th>data2</th>\n      <th>data1</th>\n      <th>data2</th>\n    </tr>\n    <tr>\n      <th>data1</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>(-2.956, -1.23]</th>\n      <td>-2.949343</td>\n      <td>-3.399312</td>\n      <td>-1.230179</td>\n      <td>1.670835</td>\n      <td>95</td>\n      <td>95</td>\n      <td>-1.657663</td>\n      <td>-0.039521</td>\n    </tr>\n    <tr>\n      <th>(-1.23, 0.489]</th>\n      <td>-1.228918</td>\n      <td>-2.989741</td>\n      <td>0.488675</td>\n      <td>3.260383</td>\n      <td>598</td>\n      <td>598</td>\n      <td>-0.328648</td>\n      <td>-0.002051</td>\n    </tr>\n    <tr>\n      <th>(0.489, 2.208]</th>\n      <td>0.489965</td>\n      <td>-3.745356</td>\n      <td>2.200997</td>\n      <td>2.954439</td>\n      <td>297</td>\n      <td>297</td>\n      <td>1.065329</td>\n      <td>0.081822</td>\n    </tr>\n    <tr>\n      <th>(2.208, 3.928]</th>\n      <td>2.212303</td>\n      <td>-1.929776</td>\n      <td>3.927528</td>\n      <td>1.765640</td>\n      <td>10</td>\n      <td>10</td>\n      <td>2.644253</td>\n      <td>0.024750</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def get_stats(group):\n",
    "    return pd.DataFrame(\n",
    "        {\"min\": group.min(), \"max\": group.max(),\n",
    "         \"count\": group.count(), \"mean\": group.mean()}\n",
    "    )\n",
    "\n",
    "\n",
    "grouped = frame.groupby(quartiles)\n",
    "grouped.apply(get_stats).unstack()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:09.988837Z",
     "end_time": "2024-04-24T20:22:10.525605Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "outputs": [],
   "source": [
    "grouping = pd.qcut(frame.data1, 10, labels=False)\n",
    "grouped = frame.data2.groupby(grouping)\n",
    "#grouped.apply(get_stats).unstack()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.039440Z",
     "end_time": "2024-04-24T20:22:10.578992Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 示例：用特定于分组的值填充缺失值"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "outputs": [
    {
     "data": {
      "text/plain": "0         NaN\n1   -0.125921\n2         NaN\n3   -0.884475\n4         NaN\n5    0.227290\ndtype: float64"
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = pd.Series(np.random.randn(6))\n",
    "s[::2] = np.nan\n",
    "s"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.065202Z",
     "end_time": "2024-04-24T20:22:10.578992Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "outputs": [
    {
     "data": {
      "text/plain": "0   -0.261035\n1   -0.125921\n2   -0.261035\n3   -0.884475\n4   -0.261035\n5    0.227290\ndtype: float64"
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s.fillna(s.mean())"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.081989Z",
     "end_time": "2024-04-24T20:22:10.578992Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "outputs": [
    {
     "data": {
      "text/plain": "Ohio          0.922264\nNew York     -2.153545\nVermont      -0.365757\nFlorida      -0.375842\nOregon        0.329939\nNevada        0.981994\nCalifornia    1.105913\nIdaho        -1.613716\ndtype: float64"
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "states = ['Ohio', 'New York', 'Vermont', 'Florida', 'Oregon', 'Nevada', 'California', 'Idaho']\n",
    "group_key = ['East'] * 4 + ['West'] * 4\n",
    "data = pd.Series(np.random.randn(8), index=states)\n",
    "data"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.104918Z",
     "end_time": "2024-04-24T20:22:10.642372Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "outputs": [
    {
     "data": {
      "text/plain": "Ohio          0.922264\nNew York     -2.153545\nVermont            NaN\nFlorida      -0.375842\nOregon        0.329939\nNevada             NaN\nCalifornia    1.105913\nIdaho              NaN\ndtype: float64"
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[['Vermont', 'Nevada', 'Idaho']] = np.nan\n",
    "data"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.124686Z",
     "end_time": "2024-04-24T20:22:10.707595Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "outputs": [
    {
     "data": {
      "text/plain": "East   -0.535707\nWest    0.717926\ndtype: float64"
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.groupby(group_key).mean()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.132387Z",
     "end_time": "2024-04-24T20:22:10.799034Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "outputs": [
    {
     "data": {
      "text/plain": "East  Ohio          0.922264\n      New York     -2.153545\n      Vermont      -0.535707\n      Florida      -0.375842\nWest  Oregon        0.329939\n      Nevada        0.717926\n      California    1.105913\n      Idaho         0.717926\ndtype: float64"
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.groupby(group_key).apply(lambda g: g.fillna(g.mean()))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.161071Z",
     "end_time": "2024-04-24T20:22:10.874336Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "outputs": [
    {
     "data": {
      "text/plain": "East  Ohio          0.922264\n      New York     -2.153545\n      Vermont       0.500000\n      Florida      -0.375842\nWest  Oregon        0.329939\n      Nevada       -1.000000\n      California    1.105913\n      Idaho        -1.000000\ndtype: float64"
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fill_values = {'East': 0.5, 'West': -1}\n",
    "data.groupby(group_key).apply(lambda g: g.fillna(fill_values[g.name]))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.182920Z",
     "end_time": "2024-04-24T20:22:10.958465Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 示例：随机采样和排列"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "outputs": [
    {
     "data": {
      "text/plain": "AH      1\n2H      2\n3H      3\n4H      4\n5H      5\n6H      6\n7H      7\n8H      8\n9H      9\n10H    10\nJH     10\nKH     10\nQH     10\ndtype: int64"
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "suits = [\"H\", \"S\", \"C\", \"D\"]  # Hearts, Spades, Clubs, Diamonds\n",
    "card_val = (list(range(1, 11)) + [10] * 3) * 4\n",
    "base_names = [\"A\"] + list(range(2, 11)) + [\"J\", \"K\", \"Q\"]\n",
    "cards = []\n",
    "for suit in suits:\n",
    "    cards.extend(str(num) + suit for num in base_names)\n",
    "\n",
    "deck = pd.Series(card_val, index=cards)\n",
    "deck.head(13)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.201279Z",
     "end_time": "2024-04-24T20:22:11.022908Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "outputs": [
    {
     "data": {
      "text/plain": "AD     1\n8C     8\n5H     5\nKC    10\n2C     2\ndtype: int64"
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def draw(deck, n=5):\n",
    "    return deck.sample(n)\n",
    "\n",
    "\n",
    "draw(deck)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.226535Z",
     "end_time": "2024-04-24T20:22:11.091150Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "outputs": [
    {
     "data": {
      "text/plain": "C  2C     2\n   3C     3\nD  KD    10\n   8D     8\nH  KH    10\n   3H     3\nS  2S     2\n   4S     4\ndtype: int64"
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def get_suit(card):\n",
    "    # last letter is suit\n",
    "    return card[-1]\n",
    "\n",
    "\n",
    "deck.groupby(get_suit).apply(draw, n=2)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.246753Z",
     "end_time": "2024-04-24T20:22:11.091150Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "outputs": [
    {
     "data": {
      "text/plain": "KC    10\nJC    10\nAD     1\n5D     5\n5H     5\n6H     6\n7S     7\nKS    10\ndtype: int64"
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "deck.groupby(get_suit, group_keys=False).apply(draw, n=2)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.262704Z",
     "end_time": "2024-04-24T20:22:11.091150Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 示例：分组加权平均数和相关系数"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "outputs": [
    {
     "data": {
      "text/plain": "  category      data   weights\n0        a  1.561587  0.957515\n1        a  1.219984  0.347267\n2        a -0.482239  0.581362\n3        a  0.315667  0.217091\n4        b -0.047852  0.894406\n5        b -0.454145  0.918564\n6        b -0.556774  0.277825\n7        b  0.253321  0.955905",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>category</th>\n      <th>data</th>\n      <th>weights</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>a</td>\n      <td>1.561587</td>\n      <td>0.957515</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>a</td>\n      <td>1.219984</td>\n      <td>0.347267</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>a</td>\n      <td>-0.482239</td>\n      <td>0.581362</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>a</td>\n      <td>0.315667</td>\n      <td>0.217091</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>b</td>\n      <td>-0.047852</td>\n      <td>0.894406</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <td>b</td>\n      <td>-0.454145</td>\n      <td>0.918564</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <td>b</td>\n      <td>-0.556774</td>\n      <td>0.277825</td>\n    </tr>\n    <tr>\n      <th>7</th>\n      <td>b</td>\n      <td>0.253321</td>\n      <td>0.955905</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.DataFrame({\"category\": [\"a\", \"a\", \"a\", \"a\",\n",
    "                                \"b\", \"b\", \"b\", \"b\"],\n",
    "                   \"data\": np.random.standard_normal(8),\n",
    "                   \"weights\": np.random.uniform(size=8)})\n",
    "df"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.281514Z",
     "end_time": "2024-04-24T20:22:11.091150Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "outputs": [
    {
     "data": {
      "text/plain": "category\na    0.811643\nb   -0.122262\ndtype: float64"
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped = df.groupby(\"category\")\n",
    "\n",
    "\n",
    "def get_wavg(group):\n",
    "    return np.average(group[\"data\"], weights=group[\"weights\"])\n",
    "\n",
    "\n",
    "grouped.apply(get_wavg)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.295939Z",
     "end_time": "2024-04-24T20:22:11.269739Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "DatetimeIndex: 2214 entries, 2003-01-02 to 2011-10-14\n",
      "Data columns (total 4 columns):\n",
      " #   Column  Non-Null Count  Dtype  \n",
      "---  ------  --------------  -----  \n",
      " 0   AAPL    2214 non-null   float64\n",
      " 1   MSFT    2214 non-null   float64\n",
      " 2   XOM     2214 non-null   float64\n",
      " 3   SPX     2214 non-null   float64\n",
      "dtypes: float64(4)\n",
      "memory usage: 86.5 KB\n"
     ]
    }
   ],
   "source": [
    "close_px = pd.read_csv(\"examples/stock_px.csv\", parse_dates=True,\n",
    "                       index_col=0)\n",
    "close_px.info()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.322190Z",
     "end_time": "2024-04-24T20:22:11.269739Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "outputs": [
    {
     "data": {
      "text/plain": "              AAPL   MSFT    XOM      SPX\n2011-10-11  400.29  27.00  76.27  1195.54\n2011-10-12  402.19  26.96  77.16  1207.25\n2011-10-13  408.43  27.18  76.37  1203.66\n2011-10-14  422.00  27.27  78.11  1224.58",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>AAPL</th>\n      <th>MSFT</th>\n      <th>XOM</th>\n      <th>SPX</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>2011-10-11</th>\n      <td>400.29</td>\n      <td>27.00</td>\n      <td>76.27</td>\n      <td>1195.54</td>\n    </tr>\n    <tr>\n      <th>2011-10-12</th>\n      <td>402.19</td>\n      <td>26.96</td>\n      <td>77.16</td>\n      <td>1207.25</td>\n    </tr>\n    <tr>\n      <th>2011-10-13</th>\n      <td>408.43</td>\n      <td>27.18</td>\n      <td>76.37</td>\n      <td>1203.66</td>\n    </tr>\n    <tr>\n      <th>2011-10-14</th>\n      <td>422.00</td>\n      <td>27.27</td>\n      <td>78.11</td>\n      <td>1224.58</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "close_px.tail(4)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.361590Z",
     "end_time": "2024-04-24T20:22:11.269739Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "outputs": [
    {
     "data": {
      "text/plain": "          AAPL      MSFT       XOM  SPX\n2003  0.541124  0.745174  0.661265  1.0\n2004  0.374283  0.588531  0.557742  1.0\n2005  0.467540  0.562374  0.631010  1.0\n2006  0.428267  0.406126  0.518514  1.0\n2007  0.508118  0.658770  0.786264  1.0\n2008  0.681434  0.804626  0.828303  1.0\n2009  0.707103  0.654902  0.797921  1.0\n2010  0.710105  0.730118  0.839057  1.0\n2011  0.691931  0.800996  0.859975  1.0",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>AAPL</th>\n      <th>MSFT</th>\n      <th>XOM</th>\n      <th>SPX</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>2003</th>\n      <td>0.541124</td>\n      <td>0.745174</td>\n      <td>0.661265</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2004</th>\n      <td>0.374283</td>\n      <td>0.588531</td>\n      <td>0.557742</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2005</th>\n      <td>0.467540</td>\n      <td>0.562374</td>\n      <td>0.631010</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2006</th>\n      <td>0.428267</td>\n      <td>0.406126</td>\n      <td>0.518514</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2007</th>\n      <td>0.508118</td>\n      <td>0.658770</td>\n      <td>0.786264</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2008</th>\n      <td>0.681434</td>\n      <td>0.804626</td>\n      <td>0.828303</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2009</th>\n      <td>0.707103</td>\n      <td>0.654902</td>\n      <td>0.797921</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2010</th>\n      <td>0.710105</td>\n      <td>0.730118</td>\n      <td>0.839057</td>\n      <td>1.0</td>\n    </tr>\n    <tr>\n      <th>2011</th>\n      <td>0.691931</td>\n      <td>0.800996</td>\n      <td>0.859975</td>\n      <td>1.0</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rets = close_px.pct_change().dropna()\n",
    "by_year = rets.groupby(lambda x: x.year)\n",
    "by_year.apply(lambda g: g.corrwith(g['SPX']))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.385753Z",
     "end_time": "2024-04-24T20:22:11.285813Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "outputs": [
    {
     "data": {
      "text/plain": "2003    0.480868\n2004    0.259024\n2005    0.300093\n2006    0.161735\n2007    0.417738\n2008    0.611901\n2009    0.432738\n2010    0.571946\n2011    0.581987\ndtype: float64"
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "by_year.apply(lambda g: g['AAPL'].corr(g['MSFT']))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.431091Z",
     "end_time": "2024-04-24T20:22:11.392661Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 示例：组级别的线性回归"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "outputs": [
    {
     "data": {
      "text/plain": "           SPX  intercept\n2003  1.195406   0.000710\n2004  1.363463   0.004201\n2005  1.766415   0.003246\n2006  1.645496   0.000080\n2007  1.198761   0.003438\n2008  0.968016  -0.001110\n2009  0.879103   0.002954\n2010  1.052608   0.001261\n2011  0.806605   0.001514",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>SPX</th>\n      <th>intercept</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>2003</th>\n      <td>1.195406</td>\n      <td>0.000710</td>\n    </tr>\n    <tr>\n      <th>2004</th>\n      <td>1.363463</td>\n      <td>0.004201</td>\n    </tr>\n    <tr>\n      <th>2005</th>\n      <td>1.766415</td>\n      <td>0.003246</td>\n    </tr>\n    <tr>\n      <th>2006</th>\n      <td>1.645496</td>\n      <td>0.000080</td>\n    </tr>\n    <tr>\n      <th>2007</th>\n      <td>1.198761</td>\n      <td>0.003438</td>\n    </tr>\n    <tr>\n      <th>2008</th>\n      <td>0.968016</td>\n      <td>-0.001110</td>\n    </tr>\n    <tr>\n      <th>2009</th>\n      <td>0.879103</td>\n      <td>0.002954</td>\n    </tr>\n    <tr>\n      <th>2010</th>\n      <td>1.052608</td>\n      <td>0.001261</td>\n    </tr>\n    <tr>\n      <th>2011</th>\n      <td>0.806605</td>\n      <td>0.001514</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import statsmodels.api as sm\n",
    "\n",
    "\n",
    "def regress(data, yvar=None, xvars=None):\n",
    "    Y = data[yvar]\n",
    "    X = data[xvars]\n",
    "    X[\"intercept\"] = 1.\n",
    "    result = sm.OLS(Y, X).fit()\n",
    "    return result.params\n",
    "\n",
    "\n",
    "by_year.apply(regress, yvar=\"AAPL\", xvars=[\"SPX\"])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:10.444537Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 10.4 透视表和交叉表"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "outputs": [
    {
     "data": {
      "text/plain": "   total_bill   tip smoker  day    time  size   tip_pct\n0       16.99  1.01     No  Sun  Dinner     2  0.059447\n1       10.34  1.66     No  Sun  Dinner     3  0.160542\n2       21.01  3.50     No  Sun  Dinner     3  0.166587\n3       23.68  3.31     No  Sun  Dinner     2  0.139780\n4       24.59  3.61     No  Sun  Dinner     4  0.146808",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>total_bill</th>\n      <th>tip</th>\n      <th>smoker</th>\n      <th>day</th>\n      <th>time</th>\n      <th>size</th>\n      <th>tip_pct</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>16.99</td>\n      <td>1.01</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.059447</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>10.34</td>\n      <td>1.66</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n      <td>0.160542</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>21.01</td>\n      <td>3.50</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>3</td>\n      <td>0.166587</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>23.68</td>\n      <td>3.31</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>2</td>\n      <td>0.139780</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>24.59</td>\n      <td>3.61</td>\n      <td>No</td>\n      <td>Sun</td>\n      <td>Dinner</td>\n      <td>4</td>\n      <td>0.146808</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.586360Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "outputs": [
    {
     "data": {
      "text/plain": "                 size       tip   tip_pct  total_bill\nday  smoker                                          \nFri  No      2.250000  2.812500  0.151650   18.420000\n     Yes     2.066667  2.714000  0.174783   16.813333\nSat  No      2.555556  3.102889  0.158048   19.661778\n     Yes     2.476190  2.875476  0.147906   21.276667\nSun  No      2.929825  3.167895  0.160113   20.506667\n     Yes     2.578947  3.516842  0.187250   24.120000\nThur No      2.488889  2.673778  0.160298   17.113111\n     Yes     2.352941  3.030000  0.163863   19.190588",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>size</th>\n      <th>tip</th>\n      <th>tip_pct</th>\n      <th>total_bill</th>\n    </tr>\n    <tr>\n      <th>day</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Fri</th>\n      <th>No</th>\n      <td>2.250000</td>\n      <td>2.812500</td>\n      <td>0.151650</td>\n      <td>18.420000</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>2.066667</td>\n      <td>2.714000</td>\n      <td>0.174783</td>\n      <td>16.813333</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sat</th>\n      <th>No</th>\n      <td>2.555556</td>\n      <td>3.102889</td>\n      <td>0.158048</td>\n      <td>19.661778</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>2.476190</td>\n      <td>2.875476</td>\n      <td>0.147906</td>\n      <td>21.276667</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Sun</th>\n      <th>No</th>\n      <td>2.929825</td>\n      <td>3.167895</td>\n      <td>0.160113</td>\n      <td>20.506667</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>2.578947</td>\n      <td>3.516842</td>\n      <td>0.187250</td>\n      <td>24.120000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Thur</th>\n      <th>No</th>\n      <td>2.488889</td>\n      <td>2.673778</td>\n      <td>0.160298</td>\n      <td>17.113111</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>2.352941</td>\n      <td>3.030000</td>\n      <td>0.163863</td>\n      <td>19.190588</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.pivot_table(index=['day', 'smoker'], values=[\"size\", \"tip\", \"tip_pct\", \"total_bill\"])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.603111Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "outputs": [
    {
     "data": {
      "text/plain": "                 size             tip_pct          \nsmoker             No       Yes        No       Yes\ntime   day                                         \nDinner Fri   2.000000  2.222222  0.139622  0.165347\n       Sat   2.555556  2.476190  0.158048  0.147906\n       Sun   2.929825  2.578947  0.160113  0.187250\n       Thur  2.000000       NaN  0.159744       NaN\nLunch  Fri   3.000000  1.833333  0.187735  0.188937\n       Thur  2.500000  2.352941  0.160311  0.163863",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th></th>\n      <th colspan=\"2\" halign=\"left\">size</th>\n      <th colspan=\"2\" halign=\"left\">tip_pct</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th>smoker</th>\n      <th>No</th>\n      <th>Yes</th>\n      <th>No</th>\n      <th>Yes</th>\n    </tr>\n    <tr>\n      <th>time</th>\n      <th>day</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"4\" valign=\"top\">Dinner</th>\n      <th>Fri</th>\n      <td>2.000000</td>\n      <td>2.222222</td>\n      <td>0.139622</td>\n      <td>0.165347</td>\n    </tr>\n    <tr>\n      <th>Sat</th>\n      <td>2.555556</td>\n      <td>2.476190</td>\n      <td>0.158048</td>\n      <td>0.147906</td>\n    </tr>\n    <tr>\n      <th>Sun</th>\n      <td>2.929825</td>\n      <td>2.578947</td>\n      <td>0.160113</td>\n      <td>0.187250</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <td>2.000000</td>\n      <td>NaN</td>\n      <td>0.159744</td>\n      <td>NaN</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Lunch</th>\n      <th>Fri</th>\n      <td>3.000000</td>\n      <td>1.833333</td>\n      <td>0.187735</td>\n      <td>0.188937</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <td>2.500000</td>\n      <td>2.352941</td>\n      <td>0.160311</td>\n      <td>0.163863</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.pivot_table(index=[\"time\", \"day\"], columns=\"smoker\",\n",
    "                 values=[\"tip_pct\", \"size\"])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.637767Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "outputs": [
    {
     "data": {
      "text/plain": "                 size                       tip_pct                    \nsmoker             No       Yes       All        No       Yes       All\ntime   day                                                             \nDinner Fri   2.000000  2.222222  2.166667  0.139622  0.165347  0.158916\n       Sat   2.555556  2.476190  2.517241  0.158048  0.147906  0.153152\n       Sun   2.929825  2.578947  2.842105  0.160113  0.187250  0.166897\n       Thur  2.000000       NaN  2.000000  0.159744       NaN  0.159744\nLunch  Fri   3.000000  1.833333  2.000000  0.187735  0.188937  0.188765\n       Thur  2.500000  2.352941  2.459016  0.160311  0.163863  0.161301\nAll          2.668874  2.408602  2.569672  0.159328  0.163196  0.160803",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead tr th {\n        text-align: left;\n    }\n\n    .dataframe thead tr:last-of-type th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr>\n      <th></th>\n      <th></th>\n      <th colspan=\"3\" halign=\"left\">size</th>\n      <th colspan=\"3\" halign=\"left\">tip_pct</th>\n    </tr>\n    <tr>\n      <th></th>\n      <th>smoker</th>\n      <th>No</th>\n      <th>Yes</th>\n      <th>All</th>\n      <th>No</th>\n      <th>Yes</th>\n      <th>All</th>\n    </tr>\n    <tr>\n      <th>time</th>\n      <th>day</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"4\" valign=\"top\">Dinner</th>\n      <th>Fri</th>\n      <td>2.000000</td>\n      <td>2.222222</td>\n      <td>2.166667</td>\n      <td>0.139622</td>\n      <td>0.165347</td>\n      <td>0.158916</td>\n    </tr>\n    <tr>\n      <th>Sat</th>\n      <td>2.555556</td>\n      <td>2.476190</td>\n      <td>2.517241</td>\n      <td>0.158048</td>\n      <td>0.147906</td>\n      <td>0.153152</td>\n    </tr>\n    <tr>\n      <th>Sun</th>\n      <td>2.929825</td>\n      <td>2.578947</td>\n      <td>2.842105</td>\n      <td>0.160113</td>\n      <td>0.187250</td>\n      <td>0.166897</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <td>2.000000</td>\n      <td>NaN</td>\n      <td>2.000000</td>\n      <td>0.159744</td>\n      <td>NaN</td>\n      <td>0.159744</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Lunch</th>\n      <th>Fri</th>\n      <td>3.000000</td>\n      <td>1.833333</td>\n      <td>2.000000</td>\n      <td>0.187735</td>\n      <td>0.188937</td>\n      <td>0.188765</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <td>2.500000</td>\n      <td>2.352941</td>\n      <td>2.459016</td>\n      <td>0.160311</td>\n      <td>0.163863</td>\n      <td>0.161301</td>\n    </tr>\n    <tr>\n      <th>All</th>\n      <th></th>\n      <td>2.668874</td>\n      <td>2.408602</td>\n      <td>2.569672</td>\n      <td>0.159328</td>\n      <td>0.163196</td>\n      <td>0.160803</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.pivot_table(index=[\"time\", \"day\"], columns=\"smoker\",\n",
    "                 values=[\"tip_pct\", \"size\"], margins=True)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.659525Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "outputs": [
    {
     "data": {
      "text/plain": "day             Fri   Sat   Sun  Thur  All\ntime   smoker                             \nDinner No       3.0  45.0  57.0   1.0  106\n       Yes      9.0  42.0  19.0   NaN   70\nLunch  No       1.0   NaN   NaN  44.0   45\n       Yes      6.0   NaN   NaN  17.0   23\nAll            19.0  87.0  76.0  62.0  244",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>day</th>\n      <th>Fri</th>\n      <th>Sat</th>\n      <th>Sun</th>\n      <th>Thur</th>\n      <th>All</th>\n    </tr>\n    <tr>\n      <th>time</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Dinner</th>\n      <th>No</th>\n      <td>3.0</td>\n      <td>45.0</td>\n      <td>57.0</td>\n      <td>1.0</td>\n      <td>106</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>9.0</td>\n      <td>42.0</td>\n      <td>19.0</td>\n      <td>NaN</td>\n      <td>70</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Lunch</th>\n      <th>No</th>\n      <td>1.0</td>\n      <td>NaN</td>\n      <td>NaN</td>\n      <td>44.0</td>\n      <td>45</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>6.0</td>\n      <td>NaN</td>\n      <td>NaN</td>\n      <td>17.0</td>\n      <td>23</td>\n    </tr>\n    <tr>\n      <th>All</th>\n      <th></th>\n      <td>19.0</td>\n      <td>87.0</td>\n      <td>76.0</td>\n      <td>62.0</td>\n      <td>244</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.pivot_table(index=[\"time\", \"smoker\"], columns=\"day\",\n",
    "                 values=\"tip_pct\", aggfunc=len, margins=True)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.706363Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "outputs": [
    {
     "data": {
      "text/plain": "day                      Fri       Sat       Sun      Thur\ntime   size smoker                                        \nDinner 1    No      0.000000  0.137931  0.000000  0.000000\n            Yes     0.000000  0.325733  0.000000  0.000000\n       2    No      0.139622  0.162705  0.168859  0.159744\n            Yes     0.171297  0.148668  0.207893  0.000000\n       3    No      0.000000  0.154661  0.152663  0.000000\n            Yes     0.000000  0.144995  0.152660  0.000000\n       4    No      0.000000  0.150096  0.148143  0.000000\n            Yes     0.117750  0.124515  0.193370  0.000000\n       5    No      0.000000  0.000000  0.206928  0.000000\n            Yes     0.000000  0.106572  0.065660  0.000000\n       6    No      0.000000  0.000000  0.103799  0.000000\nLunch  1    No      0.000000  0.000000  0.000000  0.181728\n            Yes     0.223776  0.000000  0.000000  0.000000\n       2    No      0.000000  0.000000  0.000000  0.166005\n            Yes     0.181969  0.000000  0.000000  0.158843\n       3    No      0.187735  0.000000  0.000000  0.084246\n            Yes     0.000000  0.000000  0.000000  0.204952\n       4    No      0.000000  0.000000  0.000000  0.138919\n            Yes     0.000000  0.000000  0.000000  0.155410\n       5    No      0.000000  0.000000  0.000000  0.121389\n       6    No      0.000000  0.000000  0.000000  0.173706",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th></th>\n      <th>day</th>\n      <th>Fri</th>\n      <th>Sat</th>\n      <th>Sun</th>\n      <th>Thur</th>\n    </tr>\n    <tr>\n      <th>time</th>\n      <th>size</th>\n      <th>smoker</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"11\" valign=\"top\">Dinner</th>\n      <th rowspan=\"2\" valign=\"top\">1</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.137931</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.000000</td>\n      <td>0.325733</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">2</th>\n      <th>No</th>\n      <td>0.139622</td>\n      <td>0.162705</td>\n      <td>0.168859</td>\n      <td>0.159744</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.171297</td>\n      <td>0.148668</td>\n      <td>0.207893</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">3</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.154661</td>\n      <td>0.152663</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.000000</td>\n      <td>0.144995</td>\n      <td>0.152660</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">4</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.150096</td>\n      <td>0.148143</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.117750</td>\n      <td>0.124515</td>\n      <td>0.193370</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">5</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.206928</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.000000</td>\n      <td>0.106572</td>\n      <td>0.065660</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.103799</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"10\" valign=\"top\">Lunch</th>\n      <th rowspan=\"2\" valign=\"top\">1</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.181728</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.223776</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">2</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.166005</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.181969</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.158843</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">3</th>\n      <th>No</th>\n      <td>0.187735</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.084246</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.204952</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">4</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.138919</td>\n    </tr>\n    <tr>\n      <th>Yes</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.155410</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.121389</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <th>No</th>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.000000</td>\n      <td>0.173706</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tips.pivot_table(index=[\"time\", \"size\", \"smoker\"], columns=\"day\",\n",
    "                 values=\"tip_pct\", fill_value=0)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.748503Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 交叉表：crosstab"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "outputs": [
    {
     "data": {
      "text/plain": "   Sample Nationality    Handedness\n0       1         USA  Right-handed\n1       2       Japan   Left-handed\n2       3         USA  Right-handed\n3       4       Japan  Right-handed\n4       5       Japan   Left-handed\n5       6       Japan  Right-handed\n6       7         USA  Right-handed\n7       8         USA   Left-handed\n8       9       Japan  Right-handed\n9      10         USA  Right-handed",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Sample</th>\n      <th>Nationality</th>\n      <th>Handedness</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>1</td>\n      <td>USA</td>\n      <td>Right-handed</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>2</td>\n      <td>Japan</td>\n      <td>Left-handed</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>3</td>\n      <td>USA</td>\n      <td>Right-handed</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>4</td>\n      <td>Japan</td>\n      <td>Right-handed</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>5</td>\n      <td>Japan</td>\n      <td>Left-handed</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <td>6</td>\n      <td>Japan</td>\n      <td>Right-handed</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <td>7</td>\n      <td>USA</td>\n      <td>Right-handed</td>\n    </tr>\n    <tr>\n      <th>7</th>\n      <td>8</td>\n      <td>USA</td>\n      <td>Left-handed</td>\n    </tr>\n    <tr>\n      <th>8</th>\n      <td>9</td>\n      <td>Japan</td>\n      <td>Right-handed</td>\n    </tr>\n    <tr>\n      <th>9</th>\n      <td>10</td>\n      <td>USA</td>\n      <td>Right-handed</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from io import StringIO\n",
    "\n",
    "data = \"\"\"Sample  Nationality  Handedness\n",
    "1   USA  Right-handed\n",
    "2   Japan    Left-handed\n",
    "3   USA  Right-handed\n",
    "4   Japan    Right-handed\n",
    "5   Japan    Left-handed\n",
    "6   Japan    Right-handed\n",
    "7   USA  Right-handed\n",
    "8   USA  Left-handed\n",
    "9   Japan    Right-handed\n",
    "10  USA  Right-handed\"\"\"\n",
    "data = pd.read_table(StringIO(data), sep=\"\\s+\")\n",
    "data"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.772081Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "outputs": [
    {
     "data": {
      "text/plain": "Handedness   Left-handed  Right-handed  All\nNationality                                \nJapan                  2             3    5\nUSA                    1             4    5\nAll                    3             7   10",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th>Handedness</th>\n      <th>Left-handed</th>\n      <th>Right-handed</th>\n      <th>All</th>\n    </tr>\n    <tr>\n      <th>Nationality</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>Japan</th>\n      <td>2</td>\n      <td>3</td>\n      <td>5</td>\n    </tr>\n    <tr>\n      <th>USA</th>\n      <td>1</td>\n      <td>4</td>\n      <td>5</td>\n    </tr>\n    <tr>\n      <th>All</th>\n      <td>3</td>\n      <td>7</td>\n      <td>10</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.crosstab(data[\"Nationality\"], data[\"Handedness\"], margins=True)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.794909Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "outputs": [
    {
     "data": {
      "text/plain": "smoker        No  Yes  All\ntime   day                \nDinner Fri     3    9   12\n       Sat    45   42   87\n       Sun    57   19   76\n       Thur    1    0    1\nLunch  Fri     1    6    7\n       Thur   44   17   61\nAll          151   93  244",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>smoker</th>\n      <th>No</th>\n      <th>Yes</th>\n      <th>All</th>\n    </tr>\n    <tr>\n      <th>time</th>\n      <th>day</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th rowspan=\"4\" valign=\"top\">Dinner</th>\n      <th>Fri</th>\n      <td>3</td>\n      <td>9</td>\n      <td>12</td>\n    </tr>\n    <tr>\n      <th>Sat</th>\n      <td>45</td>\n      <td>42</td>\n      <td>87</td>\n    </tr>\n    <tr>\n      <th>Sun</th>\n      <td>57</td>\n      <td>19</td>\n      <td>76</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <td>1</td>\n      <td>0</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th rowspan=\"2\" valign=\"top\">Lunch</th>\n      <th>Fri</th>\n      <td>1</td>\n      <td>6</td>\n      <td>7</td>\n    </tr>\n    <tr>\n      <th>Thur</th>\n      <td>44</td>\n      <td>17</td>\n      <td>61</td>\n    </tr>\n    <tr>\n      <th>All</th>\n      <th></th>\n      <td>151</td>\n      <td>93</td>\n      <td>244</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.crosstab([tips[\"time\"], tips[\"day\"]], tips[\"smoker\"], margins=True)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.816679Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2024-04-24T20:22:11.843864Z",
     "end_time": "2024-04-24T20:22:12.492464Z"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
